//
// Created by jiaxv on 25-8-15.
//

#include "rdf.h"

#include "as_entity.h"
#include "ipv6_parse.h"

rdf_entity_t *init_rdf_entity() {
    rdf_entity_t *rdf_entity = malloc(sizeof(rdf_entity_t));

    return rdf_entity;
}

void free_rdf_entity(rdf_entity_t *entity) {
    free(entity);
}


static l_err rdf_server_handler(basic_conn_t *bc) {
    if (!bc || !bc->read_pkt ) {
        log_error("RDF server recv failed");
        return LD_ERR_NULL;
    }
    element_propt_t *element_propt = (element_propt_t *) bc;

    net_ctx_t *ctx = bc->opt;
    meta_service_t *meta = ctx->arg;

    if (g1u_2_gau(meta->net_ele, element_propt->bc.read_pkt, element_propt) != LD_OK) {
        cn_log_error(meta->net_ele->element_tag, meta->interface_type, "Handle Message Failed!");
        return LD_ERR_INVALID;
    }

    return LD_OK;
}

static l_err rdf_client_handler(basic_conn_t *bc) {
    if (!bc || !bc->read_pkt ) {
        log_error("RDF server recv failed");
        return LD_ERR_NULL;
    }
    element_propt_t *element_propt = (element_propt_t *) bc;

    net_ctx_t *ctx = bc->opt;
    meta_service_t *meta = ctx->arg;
    net_element_t *net_ele = meta->net_ele;

    switch (meta->interface_type) {
        case INTERFACE_G7: {
            uint8_t type = *element_propt->bc.read_pkt->ptr;

            cn_format_desc_t *recv_desc = get_non_sequential_desc(g7_format_size, g7_format_descs, type);
            if (!recv_desc) {
                cn_log_error(meta->net_ele->element_tag, meta->interface_type, "No desc");
                return LD_ERR_NULL;
            }

            if (recv_desc->recv_handler) {
                if (recv_desc->recv_handler(meta->net_ele, recv_desc, element_propt->bc.read_pkt, element_propt) != LD_OK) {
                    cn_log_error(meta->net_ele->element_tag, meta->interface_type, "Handle Message Failed!");
                    return LD_ERR_INVALID;
                }
            }else {
                cn_log_error(meta->net_ele->element_tag, meta->interface_type, "No handler");
                return LD_ERR_INVALID;
            }
            break;
        }
        case INTERFACE_GAU: {
            ipv6_tcp_t *tcp_pkt = calloc(1, sizeof(ipv6_tcp_t));
            PARSE_DSTR_PKT(element_propt->bc.read_pkt, tcp_pkt, data, ipv6_tcp_desc, 60, 0 );

            as_entity_t *as = get_as_senode_by_as_IP(net_ele->as_map, (char *)tcp_pkt->dst_address->ptr);
            if (!as) {
                cn_log_error(net_ele->element_tag, INTERFACE_G1U, "No AS found");
                free_ipv6_tcp(tcp_pkt);
                return LD_ERR_INVALID;
            }

            if (gau_2_g1u(net_ele, element_propt->bc.read_pkt, get_propt_by_ip_port(net_ele, INTERFACE_G1U, as->IP_GS, as->port_GS)) != LD_OK) {
                cn_log_error(net_ele->element_tag, INTERFACE_G1U, "Cannot forward user message");
                free_ipv6_tcp(tcp_pkt);
                return LD_ERR_INVALID;
            }

            free_ipv6_tcp(tcp_pkt);
            break;
        }
        default: {
            cn_log_error(meta->net_ele->element_tag, meta->interface_type, "Invalid Interface Type");
            return LD_ERR_INVALID;
        }
    }

    return LD_OK;
}

void *exec_rdf(void *args) {
    net_element_t *net_ele = args;
    if (!net_ele)   return NULL;
    net_ele->inline_element = init_rdf_entity();
    if (init_element_service(net_ele, rdf_server_handler, rdf_client_handler) != LD_OK) {
        return NULL;
    }
    cn_log_info(net_ele->element_tag, INTERFACE_UNDEFINED, "exec finished");

    return NULL;
}

l_err start_rdf(net_element_t *net_element) {
    cn_log_info(net_element->element_tag, INTERFACE_UNDEFINED, "start");
    pthread_create(&net_element->th, NULL, exec_rdf, net_element);
    pthread_detach(net_element->th);
    return LD_OK;
}

l_err stop_rdf(net_element_t *net_ele) {
    cn_log_error(net_ele->element_tag, INTERFACE_UNDEFINED, "stop");
    if (net_ele->inline_element) {
        free_rdf_entity(net_ele->inline_element);
    }
    return LD_OK;
}
